//==================================================================
//  Copyright (C) 2006-2007  Davide Pasca
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//==================================================================
///
///
///
///
///
//==================================================================

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gl/glew.h>
#include "psys.h"
#include "pwindow.h"
#include "fontuni.h"
#include "gfxutils.h"
#include "gadget.h"

//==================================================================
using namespace	PSYSGFX;

//==================================================================
#define EDIT_H_BORDER	2
#define EDIT_V_BORDER	2
#define H_BORDER		4
#define V_BORDER		4
#define ALPHA			1.0f

static const int	TAB_CLOSE_MARK_WD = 12;
static const int	TAB_CLOSE_MARK_HE = 12;
static const int	TAB_CLOSE_MARK_HPAD = 4;
static const int	TAB_CLOSE_MARK_VPAD = 2;

static const int	STD_ICO_WD = 10;
static const int	STD_ICO_HE = 10;

//==================================================================
/*
static float	_col_normal_bg[4]	 = { .10f, .10f, .30f, .60f };
static float	_col_mouseover_bg[4] = { .15f, .15f, .40f, .60f };
static float	_col_pressed_bg[4]	 = { .55f, .15f, .40f, .60f };
static float	_gget_frame_color[3] = { .3f, .3f, .8f };
static float	_gget_text_color_active[3] = { 1, 1, 1 };
static float	_gget_text_color_nonactive[3] = { .7f, .7f, .7f };
*/

static float	_col_toolbar_bg[4]	 = { .95f, .95f, .95f, ALPHA };

//static float	_col_normal_bg[4]	 = { .95f, .95f, .95f, ALPHA };
static float	_col_disabled_bg[4]	 = { .75f, .75f, .75f, ALPHA };
static float	_gget_frame_color1[3] = { 1.0f, 1.0f, 1.0f };
static float	_gget_frame_color2[3] = { .4f, .4f, .4f };

static float	_gget_text_coe_nonactive = 0.2f;
static float	_gget_text_coe_disabled = 0.3f;
//static float	_gget_text_color_active[3] = { 0, 0, 0 };
//static float	_gget_text_color_nonactive[3] = { .2f, .2f, .2f };
//static float	_gget_text_color_disabled[3] = { .4f, .4f, .4f };

static Color4f	_col_normal_bg( .95f, .95f, .95f, ALPHA );
static Color4f	_col_pressed_bg( .75f, .75f, 1.0f, ALPHA );
static Color4f	_col_mouseover_bg( .85f, .85f, 1.0f, ALPHA );

static Color4f	_col_toggled_bg( .85f, .85f, 1.0f, ALPHA );

//==================================================================
//== GGET_Item
//==================================================================
GGET_Item::GGET_Item( GGET_Manager *managerp, GGET_TYPE type ) :
	_managerp(managerp),
	_type(type),
	_rect(0,0,32,20),
	_ico_id(STD_ICO_NONE),
	_ico_imgp(NULL)
{
	_id = -1;
	_text[0] = 0;
	_flags = 0;

	_text_col.Set( 0, 0, 0, 1 );
}

//==================================================================
void GGET_Item::SetRect( float x, float y, float w, float h )
{
	if (_rect._x != x ||
		_rect._y != y ||
		_rect._w != w ||
		_rect._h != h )
	{
		_rect._x = x;
		_rect._y = y;
		_rect._w = w;
		_rect._h = h;
		if ( _type == GGET_TYPE_TAB )
		{
			((GGET_Tab *)this)->CalcButtFrame();
		}
		_managerp->_base_manager.InvalidateDisplay();
	}
}

//==================================================================
void GGET_Item::SetPos( float x, float y )
{
	if (_rect._x != x ||
		_rect._y != y )
	{
		_rect._x = x;
		_rect._y = y;
		if ( _type == GGET_TYPE_TAB )
		{
			((GGET_Tab *)this)->CalcButtFrame();
		}
		_managerp->_base_manager.InvalidateDisplay();
	}
}

//==================================================================
void GGET_Item::SetSize( float w, float h )
{
	if (_rect._w != w ||
		_rect._h != h )
	{
		_rect._w = w;
		_rect._h = h;
		if ( _type == GGET_TYPE_TAB )
		{
			((GGET_Tab *)this)->CalcButtFrame();
		}
		_managerp->_base_manager.InvalidateDisplay();
	}
}

//==================================================================
void GGET_Item::SetText( const TCHAR *txtp )
{
	if ( _type == GGET_TYPE_EDIT )
	{
		GGET_EditBox *eboxp = (GGET_EditBox *)this;
		_tcscpy_s( eboxp->_line_txt, txtp );
		eboxp->_cursor_pos = _tcslen( eboxp->_line_txt );
	}
	else
	{
		if ( txtp )
			_tcscpy_s( _text, txtp );
		else
			_text[0] = 0;
	}

	_managerp->_base_manager.InvalidateDisplay();
}

//==================================================================
void GGET_Item::SetTextColor( float r, float g, float b, float a )
{
	_text_col.Set( r, g, b, a );
}

//==================================================================
void GGET_Item::SetIcon( StdIcon ico_id )
{
	if ( _ico_id != ico_id )
	{
		_ico_id = ico_id;
		_managerp->_base_manager.InvalidateDisplay();
	}
}

//==================================================================
void GGET_Item::SetIcon( PUtils::ImageBase *imagep )
{
	if ( _ico_imgp != imagep )
	{
		_ico_imgp = imagep;
		_managerp->_base_manager.InvalidateDisplay();
	}
}

//==================================================================
const TCHAR *GGET_Item::GetText()
{
	if ( _type == GGET_TYPE_EDIT )
	{
		GGET_EditBox *eboxp = (GGET_EditBox *)this;
		return eboxp->_line_txt;
	}
	else
		return _text;
}

//==================================================================
void GGET_Item::Show( bool onoff )
{
	u_int	flags = _flags;

	if ( onoff )
		_flags &= ~GGET_FLG_INVISIBLE;
	else
		_flags |= GGET_FLG_INVISIBLE;


	if ( _flags != flags )
		_managerp->_base_manager.InvalidateDisplay();
}

//==================================================================
void gget_int_set( GGET_Item *ggp, int val )
{
	TCHAR	buff[256];

	_stprintf_s( buff, _T("%i"), val );
	ggp->SetText( buff );
}

//==================================================================
void gget_float_set( GGET_Item *ggp, float val )
{
	TCHAR		buff[256];

	_stprintf_s( buff, _T("%g"), val );
	ggp->SetText( buff );
}

//==================================================================
float gget_float_range_get( GGET_Item *ggp, float minval, float maxval )
{
	float	val;
	TCHAR	buff[256];

	PASSERT( ggp->GetType() == GGET_TYPE_EDIT );
	if ( ggp->GetType() != GGET_TYPE_EDIT )
		return 0;

	val = _tstof( ((GGET_EditBox *)ggp)->_line_txt );
	if ( val < minval )
	{
		val = minval;
		_stprintf_s( buff, _T("%g"), val );
		ggp->SetText( buff );
	}
	else
	if ( val > maxval )
	{
		val = maxval;
		_stprintf_s( buff, _T("%g"), val );
		ggp->SetText( buff );
	}

	return val;
}

//==================================================================
int gget_int_range_get( GGET_Item *ggp, int minval, int maxval )
{
	int		val;
	TCHAR	buff[256];

	PASSERT( ggp->GetType() == GGET_TYPE_EDIT );
	if ( ggp->GetType() != GGET_TYPE_EDIT )
		return 0;

	val = _tstoi( ((GGET_EditBox *)ggp)->_line_txt );
	if ( val < minval )
	{
		val = minval;
		_stprintf_s( buff, _T("%i"), val );
		ggp->SetText( buff );
	}
	else
	if ( val > maxval )
	{
		val = maxval;
		_stprintf_s( buff, _T("%i"), val );
		ggp->SetText( buff );
	}

	return val;
}
/*
//==================================================================
void gget_calc_size( GGET_TYPE type, const TCHAR *txtp, int out_size[2] )
{
	out_size[0] = H_BORDER * 2 + FONT_StringWidth( txtp );
	out_size[1] = V_BORDER * 2 + FONT_TextHeight();
}
*/
//==================================================================
__inline static int halign( GGET_Item *T )
{
	if ( T->_flags & GGET_DEF_FLG_ALIGN_LEFT )
		return -1;
	else
	if ( T->_flags & GGET_DEF_FLG_ALIGN_RIGHT )
		return 1;
	else
		return 0;
}
//==================================================================
__inline static int valign( GGET_Item *T )
{
	if ( T->_flags & GGET_DEF_FLG_ALIGN_TOP )
		return -1;
	else
	if ( T->_flags & GGET_DEF_FLG_ALIGN_BOTTOM )
		return 1;
	else
		return 0;
}

//==================================================================
static void drawRect( const PSYS::RectF &rect )
{
	float	w = rect._w;//-0.5f;
	float	h = rect._h;//-0.5f;

	glVertex2f( rect._x + 0, rect._y + h );
	glVertex2f( rect._x + w, rect._y + h );

	glVertex2f( rect._x + w, rect._y + 0 );
	glVertex2f( rect._x + 0, rect._y + 0 );
}

//==================================================================
static void drawRectLines( const PSYS::RectF &rect )
{
	float	w = rect._w;
	float	h = rect._h;
/*
	glVertex2f( rect._x + 0, rect._y + 0 );
	glVertex2f( rect._x + w, rect._y + 0 );

	glVertex2f( rect._x + 0, rect._y + 1 );
	glVertex2f( rect._x + 0, rect._y + h-1 );

	glVertex2f( rect._x + 1, rect._y + h );
	glVertex2f( rect._x + w-1, rect._y + h );

	glVertex2f( rect._x + w, rect._y + 1 );
	glVertex2f( rect._x + w, rect._y + h-1 );
*/
/*
	glBegin( GL_LINES );

	glVertex2f( rect._x + 0, rect._y + 0 );
	glVertex2f( rect._x + w, rect._y + 0 );

	glVertex2f( rect._x + 0, rect._y + 0 );
	glVertex2f( rect._x + 0, rect._y + h-1 );

	glVertex2f( rect._x + 0, rect._y + h );
	glVertex2f( rect._x + w, rect._y + h );

	glVertex2f( rect._x + w-1, rect._y + 0 );
	glVertex2f( rect._x + w-1, rect._y + h-1 );

	glEnd();
*/
	glBegin( GL_LINE_LOOP );
	glVertex2f( rect._x + 0, rect._y + h );
	glVertex2f( rect._x + w, rect._y + h );

	glVertex2f( rect._x + w, rect._y + 0 );
	glVertex2f( rect._x + 0, rect._y + 0 );
	glEnd();
}

//==================================================================
static void draw_frame( const PSYS::RectF &rect, bool embossed )
{
	glColor4f( 0, 0, 0, 1 );
	drawRectLines( rect );

	float x = rect._x + 1;
	float y = rect._y + 1;
	float w = rect._w - 1;
	float h = rect._h - 1;

	glBegin( GL_LINES );

		if NOT( embossed )
		{
			glColor3fv( _gget_frame_color1 );
			glVertex2f( x, y );
			glVertex2f( x, h );
			glVertex2f( x, y );
			glVertex2f( w, y );

			glColor3fv( _gget_frame_color2 );
			glVertex2f( x, h );
			glVertex2f( w+1, h );
			glVertex2f( w, h );
			glVertex2f( w, y );
		}
		else
		{
			glColor3fv( _gget_frame_color2 );
			glVertex2f( x, h );
			glVertex2f( x, y );
			glVertex2f( x, y );
			glVertex2f( w, y );
		}

	glEnd();
}

//==================================================================
static void draw_frame_tab( const PSYS::RectF &rect, bool mark_bottom )
{
	float x = rect._x;
	float y = rect._y;
	float w = rect._w;
	float h = rect._h;

	if ( mark_bottom )
	{
		glColor4f( 0, 0, 0, 1 );
		glBegin( GL_LINE_STRIP );
		glVertex2f( w*0, h*1 );
		glVertex2f( w*0, h*0 );
		glVertex2f( w*1, h*0 );
		glVertex2f( w*1, h*1 );
		glEnd();
	}

	x = rect._x + 1;
	y = rect._y + 1;
	w = rect._w - 1;
	h = rect._h - 1;

	glBegin( GL_LINES );

	glColor3fv( _gget_frame_color1 );
	glVertex2f( x, h );
	glVertex2f( x, y );
	glVertex2f( x, y );
	glVertex2f( w, y );

	glColor3fv( _gget_frame_color2 );
	/*
	if ( mark_bottom )
	{
		glVertex2f( x, h );
		glVertex2f( w, h );
	}
	*/
	glVertex2f( w, h+1 );
	glVertex2f( w, y );

	glEnd();
}

//==================================================================
static void set_font_color( const Color4f &text_col, u_int item_flags, GGET_TYPE type )
{
	if ( item_flags & GGET_FLG_DISABLED )
		glColor4fv( text_col.GetInterpolated( _col_normal_bg, _gget_text_coe_disabled ).GetArray() );
	else
	{
		if ( type == GGET_TYPE_EDIT )
		{
			if NOT( item_flags & GGET_FLG_ACTIVE )
				glColor4fv( text_col.GetInterpolated( _col_normal_bg, _gget_text_coe_nonactive ).GetArray() );
		}
		glColor4fv( text_col.GetArray() );
	}
}

//==================================================================
void GGET_StaticText::Paint()
{
	PSYS::RectF	rect = _rect;
	rect._x = 0;
	rect._y = 0;

	if ( _fill_type == FILL_TYPE_HTOOLBAR )
	{
		glDisable( GL_TEXTURE_2D );
		
		glBegin( GL_QUADS );
		glColor4fv( _col_normal_bg.GetArray() );
		glVertex2f( 0, 0 );
		glVertex2f( _rect._w, 0 );

		glColor4fv( _col_normal_bg.GetInterpolated( Color4f(0,0,0,1), 0.1f ).GetArray() );
		glVertex2f( _rect._w, _rect._h );
		glVertex2f( 0, _rect._h );
		glEnd();
	}

	if ( _text[0] )
	{
		glTranslatef( H_BORDER, V_BORDER, 0 );

		set_font_color( _text_col, _flags, _type );
		//FONT_DrawBegin();
		//FONT_puts_pos_ba( rect, halign( (GGET_Item *)this ), valign( (GGET_Item *)this ), _text );
		//FONT_DrawEnd();

		WinSys::GetFont().DrawBegin();
			WinSys::GetFont().puts_pos_ba( rect, halign( (GGET_Item *)this ), valign( (GGET_Item *)this ), _text );
		WinSys::GetFont().DrawEnd();
	}
}

//==================================================================
static void drawButtBase( u_int flags, const PSYS::RectF &rect, GGET_TYPE type )
{
	float	coe_top;// = 1;
	float	coe_bot;// = 0.7f;

	coe_top = 1;
	coe_bot = 0.85f;

	Color4f	col = _col_normal_bg;

	if ( flags & GGET_FLG_PRESSED )
	{
		//col *= _col_pressed_bg;
		col = col.GetScaledRGB( 0.95f );
	}

	if ( type == GGET_TYPE_TAB && (flags & GGET_FLG_BUTTON_TOGGLED) )
	{
		col *= _col_toggled_bg;
		//coe_top = 0.7f;
		//coe_bot = 1;
	}

	if ( flags & GGET_FLG_MOUSEOVER )
	{
		//col *= _col_mouseover_bg;
	}

	glBegin( GL_QUADS );
		glColor4fv( col.GetScaledRGB( coe_top ).GetArray() );
		glVertex2f( 0, 0 );
		glVertex2f( rect._w, 0 );

		glColor4fv( col.GetScaledRGB( coe_bot ).GetArray() );
		glVertex2f( rect._w, rect._h );
		glVertex2f( 0, rect._h );
	glEnd();
}

//==================================================================
static void drawCloseTabButt( PSYS::RectF rect )
{
	glColor4f( 1, 1.0f, 1.0f, 0.5f );

	glBegin( GL_QUADS );
	drawRect( rect );
	glEnd();

	glColor4f( 0, 0, 0, 0.5f );
	drawRectLines( rect );


	rect.Inset( 2, 2 );
	glColor4f( 0.7f, 0, 0, 1 );

	glBegin( GL_LINES );
	glVertex2f( rect._x+rect._w*0, rect._y+rect._h*0 );
	glVertex2f( rect._x+rect._w*1-1, rect._y+rect._h*1-1 );

	glVertex2f( rect._x+rect._w*0, rect._y+rect._h*1 );
	glVertex2f( rect._x+rect._w*1-1, rect._y+rect._h*0+1 );
	glEnd();

}

//==================================================================
void GGET_Item::drawIconButt( PSYS::RectF rect )
{
	rect._y += (rect._h - STD_ICO_HE) / 2;
	rect._w = STD_ICO_WD;
	rect._h = STD_ICO_HE;

	glColor4f( 1, 1.0f, 1.0f, 0.5f );

	glBegin( GL_QUADS );
	drawRect( rect );
	glEnd();

	glColor4f( 0, 0, 0, 0.5f );
	drawRectLines( rect );


	rect.Inset( 1, 1 );
	//rect._x += 0*0.5f;
	//rect._y -= 0.5f;
	//rect._w += 1;
	//rect._h += 1;

	switch ( _ico_id )
	{
	case STD_ICO_ON:
		glColor4f( 0, 0.8f, 0, 1 );
		glBegin( GL_QUADS );
		drawRect( rect );
		glEnd();
		break;

	case STD_ICO_OFF:
		glColor4f( 0.8f, 0, 0, 1 );
		glBegin( GL_QUADS );
		drawRect( rect );
		glEnd();
		break;

	case STD_ICO_MARK_ON:
		glColor4f( 0, 0, 0, 1 );
		glBegin( GL_QUADS );
		{
		float	x = rect._x + rect._w/2;
		float	y = rect._y + rect._h-1;


		glVertex2f( x-3, y-3 );
		glVertex2f( x-3, y-3+2 );
		glVertex2f( x, y+2 );
		glVertex2f( x, y );

		glVertex2f( x, y );
		glVertex2f( x, y+2 );
		glVertex2f( x+8, y-8+2 );
		glVertex2f( x+8, y-8 );
		}
		/*
		glVertex2f( rect._x, rect._y + rect._h/2 );
		glVertex2f( rect._x + rect._w/2, rect._y + rect._h-2 );
		glVertex2f( rect._x + rect._w/2, rect._y + rect._h-2 );
		glVertex2f( rect._x + rect._w + 4, rect._y - 4 );
		*/
		glEnd();
		break;
	}
}

//==================================================================
void GGET_Button::Paint()
{
	PSYS::RectF	rect = _rect;
	rect._x = 0;
	rect._y = 0;

	bool	is_pressed = (_flags & GGET_FLG_PRESSED) != 0;

	glDisable( GL_TEXTURE_2D );

	if ( _flags & GGET_FLG_CLOSE_TAB_BUTT )
	{
		if ( is_pressed )
		{
			rect._x += 1;
			rect._y += 1;
		}
		drawCloseTabButt( rect );
	}
	else
	{
		drawButtBase( _flags, _rect, _type );
		draw_frame( rect, is_pressed );

		if ( is_pressed )
		{
			rect._x += 1;
			rect._y += 1;
		}

		rect._x += H_BORDER;
		rect._y += V_BORDER;
		rect._w -= H_BORDER;
		rect._h -= V_BORDER;

		if ( _ico_id != STD_ICO_NONE )
		{
			drawIconButt( rect );

			rect._x += STD_ICO_WD + 4;
			rect._w -= STD_ICO_HE + 4;
		}

		set_font_color( _text_col, _flags, _type );
		WinSys::GetFont().DrawBegin();
		WinSys::GetFont().puts_pos_ba( rect,
						halign( (GGET_Item *)this ),
						valign( (GGET_Item *)this ), _text );
		WinSys::GetFont().DrawEnd();
	}
}

//==================================================================
void GGET_Tab::Paint()
{
	PSYS::RectF	rect = _rect;
	rect._x = 0;
	rect._y = 0;

	bool	is_pressed = (_flags & GGET_FLG_PRESSED) != 0;

	glDisable( GL_TEXTURE_2D );

		drawButtBase( _flags, _rect, _type );
		draw_frame( rect, is_pressed );
		//draw_frame_tab( rect, (_flags & GGET_FLG_BUTTON_TOGGLED) != 0 );

	if ( is_pressed )
	{
		rect._x += 1;
		rect._y += 1;
	}

	rect._x += H_BORDER;
	rect._y += V_BORDER;
	rect._w -= H_BORDER + TAB_CLOSE_MARK_WD + TAB_CLOSE_MARK_HPAD;
	rect._h -= V_BORDER;

	if ( _ico_id != STD_ICO_NONE )
	{
		drawIconButt( rect );
		
		rect._x += STD_ICO_WD + 4;
		rect._w -= STD_ICO_HE + 4;
	}

	set_font_color( _text_col, _flags, _type );

	WinSys::GetFont().DrawBegin();
	WinSys::GetFont().puts_pos_ba( rect,
					  halign( (GGET_Item *)this ),
					  valign( (GGET_Item *)this ), _text );
	WinSys::GetFont().DrawEnd();
}

//==================================================================
void GGET_Tab::CalcButtFrame()
{
	if ( _close_buttp )
	{
		_close_buttp->_rect._x = _rect._x + _rect._w - (TAB_CLOSE_MARK_WD + TAB_CLOSE_MARK_HPAD);
		_close_buttp->_rect._y = (_rect._y + _rect._h - TAB_CLOSE_MARK_HE) / 2 + 2;
		_close_buttp->_rect._w = TAB_CLOSE_MARK_WD;
		_close_buttp->_rect._h = TAB_CLOSE_MARK_HE;
	}
}

//==================================================================
void GGET_CheckBox::Paint()
{
}

//==================================================================
void GGET_EditBox::Paint()
{
TCHAR	buff[GGET_EDIT_MAX_CHARS + 32];
TCHAR	buff_cut[GGET_EDIT_MAX_CHARS + 32];
int		x_cur;
int		h_cur;

	if ( _flags & GGET_FLG_ACTIVE )
	{
		_tcsncpy_s( buff_cut, _line_txt, _cursor_pos );
		buff_cut[_cursor_pos] = 0;

		_stprintf_s( buff, _T("%s"), buff_cut );
		WinSys::GetFont().DrawBegin();
		x_cur = WinSys::GetFont().StringWidth( buff );
		h_cur = WinSys::GetFont().TextHeight() + 2;
		WinSys::GetFont().DrawEnd();
	}

	glDisable( GL_TEXTURE_2D );
		PSYS::RectF	rect = _rect;
		rect._x = 0;
		rect._y = 0;
		draw_frame( rect, false );

		glTranslatef( EDIT_H_BORDER, EDIT_V_BORDER, 0 );

		if ( _flags & GGET_FLG_ACTIVE )
		{
			glColor3f( 0, 1, 0 );
			glBegin( GL_QUADS );
				glVertex2f( x_cur, -1 );			glVertex2f( x_cur + 2, -1 );
				glVertex2f( x_cur + 2, h_cur+0 );	glVertex2f( x_cur, h_cur+0 );
			glEnd();
		}

	set_font_color( _text_col, _flags, _type );

	WinSys::GetFont().DrawBegin();
	WinSys::GetFont().puts( _line_txt );	
	WinSys::GetFont().DrawEnd();
}

//==================================================================
bool GGET_EditBox::OnKeydown( WindowEvent *eventp )
{
int		pos, len;

	bool disp_update = false;

	switch ( eventp->keycode )
	{
	case VK_LEFT:
		if ( _cursor_pos > 0 )
		{
			_cursor_pos -= 1;
			disp_update = true;
		}
		break;

	case VK_BACK:
		if ( _cursor_pos > 0 )
		{
			pos = _cursor_pos;
			len = _tcslen( _line_txt );
			memmove( _line_txt + pos - 1, _line_txt + pos, len - pos + 1 );	// + 1 includes 0 termination

			_cursor_pos -= 1;

			disp_update = true;
		}
		break;

	case VK_RIGHT:
		len = _tcslen(_line_txt);
		if ( _cursor_pos < len )
		{
			_cursor_pos += 1;
			disp_update = true;
		}
		break;

	case VK_DELETE:
		len = _tcslen( _line_txt );
		if ( _cursor_pos < len )
		{
			pos = _cursor_pos;
			memmove( _line_txt + pos, _line_txt + pos + 1, len - pos + 1 );	// + 1 includes 0 termination
			disp_update = true;
		}
		break;
	}

	return disp_update;
}

//==================================================================
static int handle_edit_is_valid_char( int keychar )
{
//	if ( (keycode >= 'a' && keycode <= 'z') || (keycode >= 'A' && keycode <= 'z') ||
//		 (keycode >= '0' && keycode <= '9') || (keycode >= '' && keycode <= '')

	if ( keychar >= 32 && keychar <= 126 )
		return 1;

	return 0;
}

//==================================================================
bool GGET_EditBox::OnKeychar( void *userdatap, WindowEvent *eventp, GGET_Callback cback )
{
int				pos, len;
TCHAR			key;

	key = eventp->keychar;//tolower( eventp->keycode );
	if ( eventp->keychar == 0x0D )
	{
		if ( cback )
		{
			cback( userdatap, _id, (GGET_Item *)this, GGET_CB_ACTION_KEYCHAR );
		}
	}
	else
	if ( handle_edit_is_valid_char( key ) )
	{
		pos = _cursor_pos;
		len = _tcslen( _line_txt );
		if ( _cursor_pos < len )
		{
			memmove( _line_txt + pos + 1, _line_txt + pos, len - pos + 1 );	// + 1 includes 0 termination
		}

		if ( len < GGET_EDIT_MAX_CHARS )
		{
			_line_txt[ pos ] = key;
			_line_txt[ len + 1 ] = 0;

			_cursor_pos += 1;
		}

		return true;
	}

	return false;
}

